package com.ai.bitcoin.redis.service.impl;

import com.ai.bitcoin.constant.Bcc;
import com.ai.bitcoin.redis.service.RedisLockService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.*;
import org.springframework.stereotype.Service;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

@Slf4j
@Service
public class RedisLockServiceImpl implements RedisLockService {
    static SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    @Autowired
    @Qualifier(value = "stringRedisTemplate")
    private RedisTemplate<String, String> stringRedisTemplate;
    @Autowired
    @Qualifier(value = "redisTemplate")
    private RedisTemplate<String, Object> redisTemplate;

    /**
     * @param key
     * @param value json string
     * @return
     */
    @Override
    public boolean insert(String key, String value) {
        stringRedisTemplate.opsForValue().set(key, value);
        String value1 = stringRedisTemplate.opsForValue().get(key);
        if (StringUtils.equals(value1, value))
            return true;
        return false;
    }

    @Override
    public boolean lock(String key, String uuid, int second) {
        String value = simpleDateFormat.format(new Date()) + Bcc.SEPARATOR + uuid;
        boolean getLock = stringRedisTemplate.opsForValue().setIfAbsent(key, value);
        if (getLock)
            return true;

        value = stringRedisTemplate.opsForValue().get(key);
        String latestTime = value.split(Bcc.SEPARATOR + "")[0];
        boolean expired = lockExpired(latestTime, second);
        if (expired) {
            latestTime = stringRedisTemplate.opsForValue().getAndSet(key, value);
            if (lockExpired(latestTime, second)) {
                log.info("key success,{}", key);
                return true;
            } else {
                log.info("被别人抢到了锁哦");
                return false;
            }
        }
        return false;
    }

    @Override
    public boolean unLock(String key) {
        return stringRedisTemplate.delete(key);
    }

    public boolean lockExpired(String latestTime, int secondLimit) {
        try {
            Date latest = simpleDateFormat.parse(latestTime);
            int second = (int) ((Calendar.getInstance().getTime().getTime() - latest.getTime()) / 1000);
            if (second > secondLimit) {
                return true;
            } else {
                return false;
            }
        } catch (ParseException e) {
            return true;
        }
    }

    //https://www.cnblogs.com/EasonJim/p/7803067.html
    public void test() {
        //添加一个 key
        ValueOperations<String, Object> value = redisTemplate.opsForValue();
        value.set("lp", "hello word");
        //获取 这个 key 的值
        System.out.println(value.get("lp"));
        //添加 一个 hash集合
        HashOperations<String, Object, Object> hash = redisTemplate.opsForHash();
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("name", "lp");
        map.put("age", "26");
        hash.putAll("lpMap", map);
        //获取 map
        System.out.println(hash.entries("lpMap"));
        //添加 一个 edits 列表
        ListOperations<String, Object> list = redisTemplate.opsForList();
        list.rightPush("lpList", "lp");
        list.rightPush("lpList", "26");
        //输出 edits
        System.out.println(list.range("lpList", 0, 1));
        //添加 一个 cacheHomePage2Redis 集合
        SetOperations<String, Object> set = redisTemplate.opsForSet();
        set.add("lpSet", "lp");
        set.add("lpSet", "26");
        set.add("lpSet", "178cm");
        //输出 cacheHomePage2Redis 集合
        System.out.println(set.members("lpSet"));
        //添加有序的 cacheHomePage2Redis 集合
        ZSetOperations<String, Object> zset = redisTemplate.opsForZSet();
        zset.add("lpZset", "lp", 0);
        zset.add("lpZset", "26", 1);
        zset.add("lpZset", "178cm", 2);
        //输出有序 cacheHomePage2Redis 集合
        System.out.println(zset.rangeByScore("lpZset", 0, 2));

        Map<String, String> maps = new HashMap<String, String>();
        maps.put("multi1", "multi1");
        maps.put("multi2", "multi2");
        maps.put("multi3", "multi3");
        redisTemplate.opsForValue().multiSet(maps);
        List<String> keys = new ArrayList<String>();
        keys.add("multi1");
        keys.add("multi2");
        keys.add("multi3");
        System.out.println(redisTemplate.opsForValue().multiGet(keys));

        stringRedisTemplate.opsForValue().set("key", "hello world");
        stringRedisTemplate.opsForValue().set("key", "redis", 6);
        System.out.println("***************" + stringRedisTemplate.opsForValue().get("key"));
    }

}
